package ha.web.games_manager;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import ha.web.database.UserId;
import ha.web.exceptions.*;
public class GameRunning {
	
	private final int TABLE_SIZE = 8;
	private static int gameCounterId = 0;
	private UserId player1;
	private UserId player2;
	private int gameId;
	String[][] table;
	String chat;
	String lastMoveP1;
	String lastMoveP2;
	
	
	//true for player1, false for player2
	private boolean playerTurn;
	private int playerTurnById;
	
	public GameRunning (UserId first, UserId sec) {
		//TODO validate
		player1 = first;
		player2 = sec;
		gameId = ++gameCounterId;
		playerTurn = true;
		playerTurnById = first.getUserID();
		table = new String[8][8];
		for(int i=0;i<8;i++) {
			for(int j=0;j<8;j++) {
				if(i<3) {
					if(i==0 && j<3)
						table[i][j] = "1";
					else if(i==1 && j<2)
						table[i][j] = "1";
					else if(i==2 && j<1)
						table[i][j] = "1";
					else
						table[i][j] = "0";
				} else if(i>4) {
					if(i==5 && j>6)
						table[i][j] = "2";
					else if(i==6 && j>5)
						table[i][j] = "2";
					else if(i==7 && j>4)
						table[i][j] = "2";
					else
						table[i][j] = "0";
				} else
					table[i][j] = "0";
					
			}
		}
		chat = "";
		lastMoveP1="";
		lastMoveP2="";
		
	}
	
	public UserId getPlayerTurn () {
		if(playerTurn)
			return player1;
		return player2;
	}
	
	public boolean itIsTurn (int user) {
		return playerTurnById==user;
	}
	
	public String getPlayerNameTurn () {
		return getPlayerTurn().getName();
	}
	
	public String getPlayerNameById(int userId) {
		if(player1.getUserID()==userId)
			return player1.getName();
		else return player2.getName();
	}
	
	public int getGameId() {
		return gameId;
	}
	
	public void switchTurn () {
		playerTurn = !playerTurn;
		playerTurnById = getPlayerTurn().getUserID();
	}
	
	public List<String> getPlayers() {
		List<String> toRet = new ArrayList<String>();
		toRet.add(player1.getName());
		toRet.add(player2.getName());
		return toRet;
	}
	
	public String getTable () {
		String toRet = "";
		for(int i=0;i<8;i++) {
			for(int j=0;j<8;j++) {
				toRet += (table[j][i]+":");
			}
		}
		return toRet;
	}
	
	public void setTable (String[][] table) {
		this.table= table;  
	}
	
	public String getChat() {
		return chat;
	}
	
	public void addLineToChat (int userId, String line) {
		if (line.equalsIgnoreCase("")) return;

		Date dNow = new Date( );
	    SimpleDateFormat ft = new SimpleDateFormat ("hh:mm:ss");
		chat+= ft.format(dNow) + " ";
	    chat += getPlayerNameById(userId);
		chat += ": ";
		chat += line;
		chat += "\n";

	}
	
	public void setLastMove(int userId,String lastMove) throws GameException {
		String[][] tmpTable = validateMove(userId,lastMove);
		if(player1.getUserID()==userId)
			lastMoveP1 =lastMove;
		else if(player2.getUserID()==userId)
			lastMoveP2 =lastMove;
		table = tmpTable;
	}

	private String[][] validateMove(int userId, String lastMove) throws GameException  {
		boolean nextMovAllowed = true;
		String[] singleMov,moves,fromStr,toStr;
		String[][] tmpTable = table;
		int fromCol,fromRow,toCol,toRow;
		String playerLabel;
		if(getPlayerNameById(userId).equals(player1.getName()))
			playerLabel = "1";
		else 
			playerLabel = "2";
		//chk turn
		if(userId!=playerTurnById)
			throw new NotYourTurnException("Not Your Turn Erroe: Stop abuse the code");
		//chk emty move
		if(lastMove=="")
			throw new EmptyMoveException("Empty Move Error: You didnt move any of your pieces ");
		//chk correct syntax 
		if(!lastMove.contains(";"))
			throw new SyntaxMoveNotValidException("Syntax Error: Missing EOL");
		moves = lastMove.split(";");
		for(int i=0;i<moves.length;i++) {
			if(!moves[i].contains("->"))
				throw new SyntaxMoveNotValidException("Syntax Error: Missing -> at move number: "+i);
			singleMov = moves[i].split("->");
			if(singleMov.length!=2)
				throw new SyntaxMoveNotValidException("Syntax Error: -> not at a right pos at move number: "+i);
			if(!singleMov[0].contains("-") || !singleMov[1].contains("-"))
				throw new SyntaxMoveNotValidException("Syntax Error: Missing - at move number: "+i);
			fromStr = singleMov[0].split("-");
			toStr = singleMov[1].split("-");
			//chk numbers are parsable
			try {
				fromCol = Integer.parseInt(fromStr[0]);
				fromRow = Integer.parseInt(fromStr[1]);
				toCol = Integer.parseInt(toStr[0]);
				toRow = Integer.parseInt(toStr[1]);
			} catch (Exception e) {
				throw new SyntaxMoveNotValidException("Syntax Error: Move nt contain parsable integer at move number: "+i);
			}
			//chk number at board bound
			chkBound(fromCol);
			chkBound(fromRow);
			chkBound(toCol);
			chkBound(toRow);
			//chk valid of from
			if(!tmpTable[fromRow][fromCol].equals(playerLabel))
				throw new MoveNotValidException("Move Validation Error: Move from square "+fromRow+"-"+fromCol+" not allowed");
			//chk valid of to 
			if(!tmpTable[toRow][toCol].equals("0"))
				throw new MoveNotValidException("Move Validation Error: Move to square "+fromRow+"-"+fromCol+" not allowed");
			//chk if allowed to play 
			if(!nextMovAllowed)
				throw new MoveNotValidException("Move Validation Error: Cannot do move number: "+i);
			//chk moves direction
			boolean isJamp = false;
			boolean isVertical = false;
			if(fromCol==toCol)
				isVertical = true;
			if(fromRow==toRow && isVertical)
					throw new MoveNotValidException("Move Validation Error: Cannot stay on same square (at move number: "+i+")");
			if(Math.abs(fromCol-toCol)>2 ||Math.abs(fromRow-toRow)>2 )
				throw new MoveNotValidException("Move Validation Error: Cannot make this move (at move number: "+i+")");
			if(Math.abs(fromCol-toCol)==2 || Math.abs(fromRow-toRow)==2)
				isJamp = true;
			//case single step
			if(!isJamp) 
				nextMovAllowed = false;
			//case jump
			if(isJamp && tmpTable[(toRow-fromRow)<0?fromRow-1:fromRow+1][(toCol-fromCol)<0?fromCol-1:fromCol+1]=="0")
				throw new MoveNotValidException("Move Validation Error: Must jump above another piece (at move number: "+i+")");
			//mark chg
			tmpTable[fromRow][fromCol] = "0"; 
			tmpTable[toRow][toCol] = playerLabel;
		}
		return tmpTable;
		
	}

	private void chkBound(int num) throws MoveOutOfBoundException {
		if(num<0 || num>(TABLE_SIZE-1))
			throw new MoveOutOfBoundException("Out Of Bound Error: Move to/from "+num+" not in the board");
	}

	public String getLastMove(int userId) {
		if(player1.getUserID()==userId)
			return lastMoveP2;
		else 
			return lastMoveP1;
	}
}
